package com.database.bean;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.AttributeOverride;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.validator.constraints.ScriptAssert;

@Entity
@Table(name="ROUND")
@AttributeOverride( name="id", column = @Column(name="id") )
@XmlRootElement
@ScriptAssert(lang = "javascript", script = "_this.startDate.before(_this.endDate)")
public class Round extends BaseBean{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	@Column(name="roundNumber")
	private Integer roundNumber=null;
	
	@Column(name="startDate")
	private Date startDate=null;
	
	@Column(name="endDate")
	private Date endDate=null;
	
	@ManyToOne(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.REFRESH})
    @JoinColumn(name="gameId")
	private Game game=null;
	
	@OneToMany(fetch = FetchType.EAGER, cascade={CascadeType.ALL}) 
	@Fetch(value = FetchMode.JOIN)
    @JoinColumn(name="roundId")
	private List<AgentType>agentTypes =new ArrayList<AgentType>();
	
	@OneToMany(fetch = FetchType.EAGER, cascade={CascadeType.ALL})
	@Fetch(value = FetchMode.JOIN)
    @JoinColumn(name="roundId")
	private List<CompanyRoundDecisionAndResult>companyRoundDecisionAndResults = new ArrayList<CompanyRoundDecisionAndResult>();
	
	@Column(name="played", columnDefinition = "BIT", length = 1)
	private boolean played;
	
	//private List<FirmSettingAndDecision> firmSettingsAndDecisions=null;
	//private List<Result> results=null;


	public Round(){
		super();
	}

	
	public Round(Integer roundNumber, Date startDate,Date endDate) {
		super();
		this.roundNumber = roundNumber;
		this.startDate = startDate;
		this.endDate=endDate;
	}

	/**
	 * Returns if this round is playable for the parameter actualDate
	 * @return
	 */
	public boolean isRoundPlayable(){
		boolean playable = false;
		Date actualDate = new Date();
		
		if(actualDate.after(this.startDate) && actualDate.before(this.endDate)){
			playable = true;
		}else{
			playable = false;
		}
		
		return playable;
	}
	
	/**
	 * 
	 * @param decres
	 */
	public void addCompanyRoundDecisionAndResut(CompanyRoundDecisionAndResult decres){
		if(this.companyRoundDecisionAndResults==null){
			this.companyRoundDecisionAndResults = new ArrayList<CompanyRoundDecisionAndResult>();
		}
		this.companyRoundDecisionAndResults.add(decres);
	}

	public Integer getRoundNumber() {
		return roundNumber;
	}

	public void setRoundNumber(Integer roundNumber) {
		this.roundNumber = roundNumber;
	}

	
	
	@Override
	public String toString() {
		return "Round [roundNumber=" + roundNumber + ", startDate=" + startDate
				+ ", endDate=" + endDate + ", game=" + game + ", agentTypes="
				+ agentTypes + ", isPlayed=" + played + "]";
	}


	public Date getStartDate() {
		return startDate;
	}


	public void setStartDate(Date startDate) {
		this.startDate = startDate;
	}


	public Date getEndDate() {
		return endDate;
	}


	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}


	public Game getGame() {
		return game;
	}


	public void setGame(Game game) {
		this.game = game;
	}


	public List<AgentType> getAgentTypes() {
		return agentTypes;
	}


	public void setAgentTypes(List<AgentType> agentTypes) {
		this.agentTypes = agentTypes;
	}


	public boolean isPlayed() {
		return played;
	}


	public void setPlayed(boolean played) {
		this.played = played;
	}
	
	public boolean allowSimulationForRound(){
		Date now=new Date();
		
		if(this.isPlayed()){
			return false;
		}
		else{
			List<Round> rounds=this.game.getRounds();
			for(Round round : rounds){
				//wenn Runde nocht nicht gespielt wurde && und sie ein kleines Startdatum hat als die this Runde
				if(!round.isPlayed() && round.startDate.before(this.startDate)){
					return false;  //return false for this
				}
			}
			if(now.after(this.startDate) && now.after(this.endDate))
				return true;
		}
		return false;
	}
	
	/**
	 * Returns the CompanyRoundDecisionAndResult-object of the actual round for a specific transferred company.
	 * @param company
	 * @return
	 */
	public CompanyRoundDecisionAndResult getDecisionsAndResultsForComp(User company){
		CompanyRoundDecisionAndResult crdar=null;
		
		if(this.companyRoundDecisionAndResults!=null){
			for(CompanyRoundDecisionAndResult c : this.companyRoundDecisionAndResults){
				if(c.getUser().getId()==company.getId()){
					crdar=c;
					break;
				}
			}		
		}
		return crdar;
	}
	
	
	/**
	 * @return the companyRoundDecisionAndResults
	 */
	public List<CompanyRoundDecisionAndResult> getCompanyRoundDecisionAndResults() {
		return companyRoundDecisionAndResults;
	}


	/**
	 * @param companyRoundDecisionAndResults the companyRoundDecisionAndResults to set
	 */
	public void setCompanyRoundDecisionAndResults(
			List<CompanyRoundDecisionAndResult> companyRoundDecisionAndResults) {
		this.companyRoundDecisionAndResults = companyRoundDecisionAndResults;
	}


	public void addAgentType(AgentType agentType){
		if(agentTypes==null)
			agentTypes=new ArrayList<AgentType>();
		
		agentTypes.add(agentType);	
	}
	
	public void removeAgentType(AgentType agentType){
		if(agentTypes==null)
			agentTypes=new ArrayList<AgentType>();
		
		agentTypes.remove(agentType);	
	}
	
	public List<Agent> getAllAgents(){
		List<Agent> allAgents=new ArrayList<Agent>();
		if(this.getAgentTypes()!=null){
			for(AgentType agentType : this.getAgentTypes()){
				if(agentType.getAgents()!=null){
					allAgents.addAll(agentType.getAgents());
				}
			}
		}
		return allAgents;
	}
	
}
